package com.quectel.dms.controller.emq;

import com.quectel.business.dms.application.ApplicationAccessConf;
import com.quectel.business.dms.application.ApplicationBusiness;
import com.quectel.core.module.application.dto.ApplicationDto;
import com.quectel.core.module.application.service.ApplicationAccessTemplateService;
import com.quectel.core.module.application.service.ApplicationService;
import com.quectel.dms.controller.BaseController;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ACL校验
 *
 * @author rananxin
 * @email: ryan.ran@quectel.com
 * @date 2021/11/18 2:21 下午
 */
@RestController
@RequestMapping("emqx")
@Tag(name = "EmqAuthController")
@Slf4j
public class EmqAuthController extends BaseController {

    @DubboReference
    private ApplicationService applicationService;
    @DubboReference
    private ApplicationAccessTemplateService applicationAccessConfService;
    @Autowired
    private ApplicationBusiness applicationBusiness;

    /**
     * 连接校验
     *
     * @param clientId
     * @param username
     * @param password
     * @param ipAddress
     * @param port
     * @param nameOfCert
     * @param subjectOfCert
     * @return
     */
    @PostMapping("auth")
    public ResponseEntity auth(String clientId, String username, String password, String ipAddress, String port
            , @RequestParam(required = false) String nameOfCert
            , @RequestParam(required = false) String subjectOfCert) {
        log.info("emqx的http连接请求验证 clientid: {} username: {} password: {} ipaddress {} port {} nameOfCert {} subjectOfCert {}"
                , clientId, username, password
                , ipAddress, port, nameOfCert, subjectOfCert);

        Map<String, Object> params = new HashMap<>();
        params.put("appId", username);

        List<ApplicationDto> applications = applicationBusiness.getApplications(null, null
                , ApplicationAccessConf.ConfCodeEnum.EMQ, params);
        if (CollectionUtils.isEmpty(applications)) {
            return new ResponseEntity(HttpStatus.UNAUTHORIZED);
        }

        for (ApplicationDto application : applications) {
            if (connectCheck(application, password)) {
                return new ResponseEntity(HttpStatus.OK);
            }
        }

        return new ResponseEntity(HttpStatus.UNAUTHORIZED);
    }

    /**
     * 校验客户端是否为超级用户，是则跳过的所有ACL校验
     *
     * @param params
     * @return
     */
    @PostMapping("superRequest")
    public ResponseEntity superRequest(@RequestParam Map<String, Object> params) {
        return new ResponseEntity(HttpStatus.UNAUTHORIZED);
    }

    /**
     * 订阅和推送校验
     *
     * @param access
     * @param username
     * @param clientId
     * @param ipAddr
     * @param topic
     * @param port
     * @param mountPoint
     * @return
     */
    @PostMapping("acl")
    public ResponseEntity acl(String access, String username, String clientId, String ipAddr, String topic, String port
            , @RequestParam(required = false) String mountPoint) {
        logger.info("emqx的ACL请求验证 access: {} username: {} clientId: {} ipAddr {} topic {} port {} mountpoint {}"
                , access, username, clientId, ipAddr, topic, port, mountPoint);
        Map<String, Object> params = new HashMap<>();
        params.put("appId", username);

        List<ApplicationDto> applications = applicationBusiness.getApplications(null, null
                , ApplicationAccessConf.ConfCodeEnum.EMQ, params);
        if (CollectionUtils.isEmpty(applications)) {
            return new ResponseEntity(HttpStatus.UNAUTHORIZED);
        }

        return new ResponseEntity(HttpStatus.OK);
    }

    private boolean connectCheck(ApplicationDto appDto, String secret) {
        ApplicationAccessConf.TemplateOfEmqConf templateOfEmqConf
                = ApplicationAccessConf.parseExtStr(ApplicationAccessConf.TemplateOfEmqConf.class, appDto.getAccessConf());
        if (StringUtils.isNotBlank(templateOfEmqConf.getAppSecret()) && templateOfEmqConf.getAppSecret().equals(secret)) {
            return true;
        }
        return false;
    }
}
